package com.hsmpay.mobile.action.account.fc;

import com.hsmpay.common.pojo.BasePojo;
import com.hsmpay.common.pojo.qian4.Qian4SendLog;
import com.hsmpay.common.pojo.user.User;
import com.hsmpay.common.util.DateConvertUtil;
import com.hsmpay.common.util.NumberUtil;
import com.hsmpay.mobile.pojo.other.Settings;
import com.hsmpay.mobile.pojo.system.Holidays;
import com.hsmpay.mobile.pojo.terminal.Tchannel;
import com.hsmpay.mobile.pojo.terminal.TerminalPrivileges;
import com.hsmpay.mobile.pojo.trans.SSBindCards;
import com.hsmpay.mobile.pojo.trans.TransOrder;
import com.hsmpay.mobile.pojo.trans.TransPriorSettle;
import com.hsmpay.mobile.pojo.user.UserMoney;
import com.hsmpay.mobile.pojo.user.UserTransLimit;
import com.hsmpay.mobile.service.account.CashMoneyService;
import com.hsmpay.mobile.service.other.SettingsService;
import com.hsmpay.mobile.service.system.HolidaysService;
import com.hsmpay.mobile.service.trans.SSBindCardsService;
import com.hsmpay.mobile.service.user.UserMoneyService;
import com.hsmpay.mobile.service.user.UserTransLimitService;
import com.hsmpay.qian4.pojo.PurchaseResult;
import com.hsmpay.qian4.pojo.send.ICCardParam;
import com.hsmpay.utils.system.ConConfig;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.*;

/**
 * 收款 action
 *
 * @author 颜铃璋
 * @date 2013-8-27
 */
@Controller("purchaseAction")
@Scope("prototype")
public class PurchaseAction extends PurchaseBaseAction {
    private static final long serialVersionUID = 7459445231353195197L;
    private static Logger log = Logger.getLogger(PurchaseAction.class);

    private String transAmt;
    private String accountNumber;

    @Resource(name = "userTransLimitService")
    private UserTransLimitService<BasePojo, Long> userTransLimitService;
    @Resource(name = "settingsService")
    protected SettingsService<Settings, Long> settingsService;
    @Resource(name = "ssBindCardsService")
    private SSBindCardsService<SSBindCards, Long> bindCardsService; // 秒到业务
    @Resource(name = "holidaysService")
    private HolidaysService<Holidays, Long> holidaysService;
    @Resource(name = "cashMoneyService")
    private CashMoneyService<TransOrder, Long> cashMoneyService;
    @Resource(name = "userMoneyService")
    private UserMoneyService<UserMoney, Long> userMoneyService;
    /**
     * 我要收款
     *
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unused")
    public String receivablesToCard() throws Exception {
        log.debug("--- receivablesToCard() start ---");
        JSONObject js = JSONObject.fromObject(getRequest().getAttribute(FC_DATA));
        terminalTypeId = Long.parseLong(js.getString("terminalTypeId"));
        if (js.containsKey("userId"))
            userId = Long.parseLong(js.getString("userId"));
        if (js.containsKey("transAmt"))
            transAmt = js.getString("transAmt");
        if (js.containsKey("accountNumber"))
            accountNumber = js.getString("accountNumber");
        roleId = Long.parseLong(getJsonString("roleId"));
        //查询用户
        User user = userService.getUserById(userId);
        if (!user.getRoleId().equals(roleId) && user.getRoleId() != 1L && roleId != 4L && roleId != 5L) {//这块添加过滤零费率支付
            log.error("前台传入roleId = " + roleId + " 与当前用户注册roleId = " + user.getRoleId() + "不相符!");
            Map<String, Object> resMap = new HashMap<String, Object>();
            resMap.put("reqCode", "0001");
            resMap.put("reqMsg", "收款交易时,roleId参数异常!");
            sendAppMsg(resMap);
            return null;
        }

        double money = Double.parseDouble(transAmt) / 100;
        Map<String, Object> map = userTransLimitService.transCheck(userId, roleId, accountNumber, money, 1L, "RECEIVABLES", user.getChannelId().intValue());
        if (map != null) {
            sendAppErrorMsg(map.get("code").toString(), map.get("value").toString());
            return null;
        }


        //屏蔽伪卡
        if (transRefuseCardService.isRefuseCard(accountNumber)) {
            sendAppErrorMsg("6073", accountNumber);
            return null;
        }

        //支付  接口
        payOrder(user, roleId);
        return null;
    }

    private Boolean checkIcInfo(Qian4SendLog sendLog) {
        ICCardParam icCardParam;
        if (sendLog != null && sendLog.getIccParam() != null)
            icCardParam = sendLog.getIccParam();
        else return false;
        return StringUtils.isNotEmpty(icCardParam.getBit55());
        // return sendLog.getIccParam().getBit55().isEmpty();
    }

    /**
     * 我要收款
     *
     * @return
     * @throws Exception
     */
    public String payOrder(User user, long roleId) throws Exception {
        functionKey = "RECEIVABLES";
        Qian4SendLog send = null;//发送数据
        TransPriorSettle transPriorSettle = null;
        TransOrder transOrder = null;
        Map<String, Object> result = null;
        try {
            if (!checkPIV(functionKey)) {
                log.warn("我要收款时, 银行接口暂停使用！");
                return null;
            }
            user = userService.getUserById(userId);

            if (null != user) {
                User user1 = new User();
                user1.setId(userId);
                user1.setDeleted(0);
                user = userService.searchEntity(user1);
                if (user == null) {
                    Map<String, Object> resMap = new HashMap<String, Object>();
                    log.warn("我要收款时, 用户Id=" + userId + " 对应的用户不存在!");
                    resMap.put("reqCode", "6004");
                    resMap.put("reqMsg", "用户：" + userId + " 该用户被销户或暂停使用！");
                    resMap.put("channelId", "");
                    sendAppMsg(resMap);
                    return null;
                }
                //获取user对应的刷卡器类型
                Integer machineType = user.getMachineType();
                Object[] resultA = assembleBean(user);
                if (null == resultA) return null;

                send = (Qian4SendLog) resultA[0];
                transOrder = (TransOrder) resultA[1];

                //添加刷卡器类型
                transOrder.setMachineType(machineType);
                int channelId = user.getChannelId().intValue();
                //添加判断:通道是否支持复合卡刷磁条, 是否需要跳转到其他通道
                channelId = whetherChangeChannel(String.valueOf(channelId), send);

                Tchannel tc = tchannelService.searchMobileTchannelByCode(channelId);
                send.setCollectionType(tc.getCode());
                send.setRoleId(roleId);
                double fee = calculateFee(user, transOrder.getRoleId(), transOrder.getTransMoney(), transOrder.getFeeRate());

                transOrder.setFeeMoney(fee);
                transOrder.setChargeAmount(transOrder.getTransMoney() - fee);
                //获取数据库中e点的交易限额
                UserTransLimit limit = new UserTransLimit();
                limit.setFunctionKey("EPOINTTRANSLIMIT");
                limit = (UserTransLimit) userTransLimitService.searchEntity(limit);
                long dayCnt = limit.getDayCnt();//得到e点的限额

                switch (channelId) {
                    case PurchaseBaseAction.TC_EPOINT:
                        if (dayCnt > transOrder.getTransMoney()) {
                            send = ds_ECBService.initSend(send, tc);
                            send.setCollectionType(PurchaseBaseAction.TC_ECB);
                        } else {
                            send = ds_ideaioeService.initSend(send, tc);
                        }
                        break;
                    case PurchaseBaseAction.TC_ECB:
                        send = ds_ECBService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_RuiSheng:
                        send = ds_RuiShengService.initSend(send, tc);
                        if (send.getBatchId() == null) {
                            tc = tchannelService.searchMobileTchannelByCode(PurchaseBaseAction.TC_ECB);
                            send = ds_ECBService.initSend(send, tc);
                            send.setCollectionType(PurchaseBaseAction.TC_ECB);
                        }
                        break;
                    case PurchaseBaseAction.TC_RuiSheng_GT:
                        send = ds_RuiShengGTService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGYI:
                        send = ds_zytlPayService.initSend(send);
                        break;
                    case PurchaseBaseAction.TC_POSP:
                        send = ds_pospService.initSend(send, tc, user.getId());
                        break;
                    case PurchaseBaseAction.TC_Uinpay:
                        send = ds_uinpayPayService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_YinShengBao:
                        send = ds_yinShengBaoService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_POS:
                        send = ds_posService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHIFUTONG:
                        send = ds_zhifutongService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_HANXIN:
                        send = ds_HanXinService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGLAN:
                        send = ds_zhongLanService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_KAYINKA:
                        send = ds_kaYinKaService.initSend(send, tc);
                        break;
                }

                //下订单
                transPriorSettle = accountManageQ4Service.advanceOrder(transOrder, send, send.getCollectionType());

                //提交给 Q48 接口
                PurchaseResult rs = null;
                switch (send.getCollectionType()) {
                    case PurchaseBaseAction.TC_ECB:
                        rs = ds_ECBService.billPayment(send, tc);
                        break;//ECB
                    case PurchaseBaseAction.TC_RuiSheng:
                        rs = ds_RuiShengService.billPayment(send, tc);
                        break;//瑞晟
                    case PurchaseBaseAction.TC_RuiSheng_GT:
                        rs = ds_RuiShengGTService.billPayment(send, tc);
                        break;//瑞晟
                    case PurchaseBaseAction.TC_ZHONGYI:
                        long amtLimit = Long.valueOf(ConConfig.getAttribute("ZYTL_FDORFL_AMT_LIMIT"));
                        long transMoney = Long.valueOf(send.getTransAmt());
                        if (transMoney > amtLimit) {
                            send.setRoleId(3l);
                        } else {
                            send.setRoleId(2l);
                        }
                        rs = ds_zytlPayService.purchase(send, transOrder.getSignaturePath());
                        break;//ZYTL
                    case PurchaseBaseAction.TC_POSP:
                        rs = ds_pospService.billPayment(send, tc);//pos
                        break;
                    case PurchaseBaseAction.TC_EPOINT:
                        rs = ds_ideaioeService.billPayment(send, tc);//E点
                        break;
                    case PurchaseBaseAction.TC_Uinpay:
                        rs = ds_uinpayPayService.billPayment(send, tc);//优银
                        break;
                    case PurchaseBaseAction.TC_YinShengBao:
                        rs = ds_yinShengBaoService.billPayment(send, tc);//银生宝
                        break;
                    case PurchaseBaseAction.TC_POS:
                        rs = ds_posService.billPayment(send, tc);//大POS
                        break;
                    case PurchaseBaseAction.TC_ZHIFUTONG:
                        rs = ds_zhifutongService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_HANXIN:
                        rs = ds_HanXinService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGLAN:
                        rs = ds_zhongLanService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_KAYINKA:
                        rs = ds_kaYinKaService.billPayment(send, tc);
                        break;
                }

                //解析结果
                result = purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);
                log.debug(result);
                sendAppMsg(result);
            } else {
                log.warn("收款交易时, 用户Id=" + userId + " 对应的用户不存在!");
                sendAppErrorMsg("6012", userId + "");
            }
        } catch (Exception e) {
            e.printStackTrace();
            revocationOrderTimeOut(send, transPriorSettle);
            throw e;
        } finally {
            send = null;
            transPriorSettle = null;
            transOrder = null;
            result = null;
        }
        return null;
    }

    /**
     * 自动将 秒到订单生成提现订单
     * @param transOrder
     */
    private void settileSecCashMoney(TransOrder transOrder) throws Exception {
        String orderNum = transOrder.getOrderNum();
        String functionKey = "SECONDSTO_CASHMONEY";
        //int isCardCer = 1;//收款时  付款卡号是否  认证 0 代表认证失败 1 认证成功 2 未审核  3 未认证
        try{
            Date date = new Date();
            if (!checkTime(date)) {//检测时间
                return;
            }
            User user = userService.getUserById(transOrder.getUserId());
            if (!checkCashStatus(functionKey)) {//这块要添加根据机构判断情况
                log.warn("秒到提现时, 银行接口暂停使用！");
                return;
            }
            //判断用户 结算状态
            if (user.getClearStatus() == null || user.getClearStatus().intValue() != 1) {
                String message =  "用户存在违法，请跟管理员联系！";
                log.warn(message);
                return;
            }
            if (12 != transOrder.getOrderTypeId().intValue()) {//订单不是秒到收款订单
                log.warn("安全提现时, 订单不是收款订单！");
                return;
            }
//            if (1 != transOrder.getStatus().intValue()) {//收款订单不是交易成功的订单
//                log.warn("提现失败，收款订单不是交易成功的订单！");
//                return;
//            }

            if (!checkOrderTime(transOrder.getCreateDate())) {
                String dateStr = DateConvertUtil.dateString(transOrder.getCreateDate());
                log.warn("提现失败, 订单" + orderNum + "只能在 " + dateStr + " 22:40:00 前执行提现，对于不能提现的交易，请等待T+1结算！");
                return;
            }
            double chargeAmount = transOrder.getChargeAmount();
            //金额是否足够
            boolean isZhugou = userMoneyService.moneyTheAdequacy(transOrder.getUserId(), chargeAmount, 1);
            if (!isZhugou) {
                log.warn("交易订单" + orderNum + "提现错误，金额不足！");
                return;
            }
            double cashMoneyFee = getConfig("SECONDSTO_CASHMONEY_FEERATE");//提现手续费
            double cashMoney = NumberUtil.roundF2((chargeAmount - cashMoneyFee));//NumberUtil.numFormatToNum((chargeAmount*(1-cashMoneyFeeRate)));

            if (chargeAmount != NumberUtil.roundF2((cashMoneyFee + cashMoney)) && chargeAmount != cashMoney) {//金额不相等
                log.warn("安全提现时, 传入提现金额与手续费不符！");
                return;
            }
//            double minCashMoney = 2;
//            if (cashMoney <= minCashMoney) {
//                log.warn("交易订单" + orderNum + "提现错误，提现金额不能小于" + minCashMoney + " 元！");
//                return;
//            }
            //添加用户提现限额
            double ssCashlimit = getConfig("SECONDSTO_CASH_LIMIT");
            boolean res = userTransLimitService.cashMoneyTotalMoneyLimit(transOrder.getUserId(), cashMoney, ssCashlimit);
            if (res) {
                log.warn("提现失败,单日单用户秒到提现支持最大金额为" + ssCashlimit + "元");
                return;
            }
            //判断时间是否是周六\日 或者 是节假日并且不是法定工作日
//            if ((holidaysService.isWeekend(date) || holidaysService.isHolidays(date))
//                    && !holidaysService.isLegalWorkDay(date)) {
//
//                Settings settings= settingsService.getSettingsByFk("SPECIAL_RATES_AND_FEES");//获取周六\日T+0提现额外手续费率
//                cashRate += Double.parseDouble(settings.getMainValue());//加上周六\日额外手续率
//            }
            TransOrder order = new TransOrder();
            order.setOrderNum(getOrderNumByDate(date));
            order.setOrderTypeId(8l);//提现
            order.setUserId(transOrder.getUserId());
            order.setBrokerage(0.0000);//brokerage);
            order.setDealerBrokerage(0.0000);
            order.setRootCategory("账务管理");
            order.setCategory("秒到提现");
            order.setBankCard(transOrder.getBankCard());//收款 订单的  付款卡号 ####################################
            order.setObjectiveName(user.getCardholder());//对方姓名
            order.setObjectiveCard(user.getBankCard());//对方银行卡
            order.setObjectiveOpBank(user.getOpeningBank());//对方银行
            order.setStatus(2);
            order.setClearing(0);//结算状态 0未结算 1结算
            order.setDescription("系统结算");//交易详情
            order.setCreateDate(date);
            order.setUpdateLongTime(date.getTime());
            order.setObjectiveBBank(user.getBranchesBank());//对方。银行支行
            order.setObjectiveBBProvince(user.getBBankProvince());
            order.setObjectiveBBCity(user.getBBankCity());
            order.setObjectiveMobile(user.getMobile());//对方手机号
            order.setObjectiveBBankCode(user.getBranchesBankCode());
            //三毛接口 银行代码  鉴权
            order.setObjectiveAccBankCode(user.getAccBankCode());
            order.setTerminalTypeId(transOrder.getTerminalTypeId());
            order.setRoleId(transOrder.getRoleId());
            order.setOrgOrderNum(order.getOrderNum());//原订单编号
            order.setSignaturePath(order.getSignaturePath());//获得收款 签名

//            order.setFeeRate(user.getCashRate() < cashRate ? cashRate : user.getCashRate());//订单费率
            order.setTransMoney(chargeAmount);
            order.setFeeMoney(cashMoneyFee);//fee);//手续费
            order.setChargeAmount(cashMoney);//提现金额
            order.setFdMaxFee(0.00);//用户封顶最高
            order.setFdMinFee(2.00);//用户封顶最低
            order.setClientType(transOrder.getClientType());

            //修改原订单
            transOrderService.updateCashOrderByNum(order.getOrderNum(), transOrder.getOrderNum());

            //判断 机构预存款
            int flag = cashMoneyService.cashMoney(order);

            if (flag == 1) {
                String reqMsg = "交易订单" + orderNum +"提现成功，一小时内自动结算到您绑定的银行卡账号中！";
                log.warn(reqMsg);
            } else if (flag == 2) {//预存款不足
                //修改原订单
                log.warn("交易订单" + orderNum +"提现失败,机构预存款不足");
                transOrderService.updateCashOrderByNum(order.getOrderNum(), "");
            }
        }catch (Exception e){
            e.printStackTrace();
            transOrderService.updateCashOrderByNum(transOrder.getOrderNum(), "");
            throw e;
        }

    }
    /**
     * 从数据库中获取配置
     * @param functionKey
     * @return
     * @throws SQLException
     */
    public double getConfig(String functionKey) throws SQLException{
        double result = 0.0;
        String mainValue = null;
        if (null != settingsService.getSettingsByFk(functionKey)) {
            mainValue = settingsService.getMainValueByFk(functionKey);
            result = Double.parseDouble(mainValue);
        }
        return result;
    }

    /**
     * 检查订单时间是否可以提现
     *
     * @param orderDate
     * @return
     * @throws Exception
     */
    private boolean checkOrderTime(Date orderDate) throws Exception {
        Date tempDate = DateConvertUtil.getSpecifiedDayBefore(orderDate);
        Date startDate = DateConvertUtil.stringDateTime(DateConvertUtil.dateString(tempDate) + " 23:00:00");//昨天 23：00：00
        Date stopDate = DateConvertUtil.stringDateTime(DateConvertUtil.dateString(orderDate) + " 22:40:00");//今天 22：40：00

        Date date = new Date();

        if (date.getTime() < startDate.getTime()) {
            return false;
        } else if (date.getTime() > stopDate.getTime()) {
            return false;
        }
        return true;
    }

    /**
     * 检查功能 是否有效
     * check Privileges Is Valid
     *
     * @param functionKey
     * @return
     */
    public boolean checkCashStatus(String functionKey) throws Exception {
        TerminalPrivileges terminalPrivileges = terminalPrivilegesService.checkPrivilegesIsValid(functionKey);
        if (null == terminalPrivileges || terminalPrivileges.getStatus().intValue() == 1) {
            return true;
        }else if(terminalPrivileges.getStatus().intValue() == 2){
            log.warn("检查终端功能时, 该功能暂时停止使用！");
        }else if(terminalPrivileges.getStatus().intValue() == 3){
            log.warn("系统日切中,请稍候...");
        }
        return false;
    }

    /**
     * 检测提现时间
     * @param date
     * @return
     * @throws Exception
     */
    private boolean checkTime(Date date) throws Exception {
        //工作日 T+0 开始时间 与 结束时间
        Settings workDayT0Time = settingsService.getSettingsByFk("NORMAL_START_AND_ENDTIME");
        //节假日 T+0 是否可以提现
        String holidayT0 = settingsService.getMainValueByFk("SPECIAL_SETUP");
        boolean isT0 = false;
        if(holidayT0.equals("TRUE")){
            isT0 = true;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //是否为节假日
        boolean isHoliday = holidaysService.isRealHolidays(date);

        //节假日  t0开放
        if (isHoliday && isT0) {
            Settings holidayT0Time = settingsService.getSettingsByFk("SPECIAL_START_AND_ENDTIME");
            if (cal.get(Calendar.HOUR_OF_DAY) < Integer.parseInt(holidayT0Time.getMainValue()) || cal.get(Calendar.HOUR_OF_DAY) >= Integer.parseInt(holidayT0Time.getValue2())) {
                String message = "尊敬的用户您好，节假日提现功能功能时间只在节假日的" + holidayT0Time.getMainValue() + ":00 —— " + holidayT0Time.getValue2() + ":00 时间内提供服务！";
                log.warn(message);
                return false;
            }
        }
        //节假日  t0不开放
        if (isHoliday && !isT0) {
            String message = "尊敬的用户您好，提现功能只在工作日的" + workDayT0Time.getMainValue() + ":00 —— " + workDayT0Time.getValue2() + ":00 时间内提供服务！";
            log.warn(message);
            return false;
        }
        if (!isHoliday) {
            if (cal.get(Calendar.HOUR_OF_DAY) < Integer.parseInt(workDayT0Time.getMainValue()) || cal.get(Calendar.HOUR_OF_DAY) >= Integer.parseInt(workDayT0Time.getValue2())) {
                String message = "尊敬的用户您好，提现功能只在工作日的"+workDayT0Time.getMainValue()+":00 —— "+workDayT0Time.getValue2()+":00 时间内提供服务！";
                log.warn(message);
                return false;
            }
        }
        return true;
    }

    /**
     * 判断用户秒到的卡是否在info_user_bind_cards表中存在
     * @param accountNumber
     * @return
     */
    private boolean checkCard(String accountNumber, Long userId) throws Exception {
        boolean result = false;
        SSBindCards cards = new SSBindCards();
        cards.setUserId(userId);
        cards.setCardNumber(accountNumber);
        cards.setStatus(1);
        if (null != bindCardsService.searchEntity(cards)){
            result = true;
        }
        return result;
    }

    /**
     * 判断降级交易是否需要切换通道
     *
     * @param channelId
     * @return
     */
    private int whetherChangeChannel(String channelId, Qian4SendLog send) throws SQLException {
        if (!checkIcInfo(send) && isFhCard(send.getTrack2Data())) {
            //如果是降级交易,进行判断是否需要切换通道,需要切换通道时,从数据库获取切换到那个通道
            Settings settings = null;
            String mainValue = null;
            String value2 = null;
            if (null != settingsService.getSettingsByFk("WHETHER_CHANGE_CHANNEL")) {
                settings = settingsService.getSettingsByFk("WHETHER_CHANGE_CHANNEL");
                mainValue = settings.getMainValue().trim();
                value2 = settings.getValue2().trim();
                if (StringUtils.isNotBlank(mainValue)) {
                    if (mainValue.contains(channelId) && StringUtils.isNotBlank(value2) && !("0".equals(value2))) {
                        channelId = value2;
                    }
                }
            }
        }
        return Integer.valueOf(channelId);
    }

    /**
     * 判断是否超限
     *
     * @param transMoney
     * @return
     * @throws SQLException
     */
    private Map<String, Object> noInterestRateLimit(Double transMoney) throws SQLException {
        Map<String, Object> limitMap = new HashMap<String, Object>();
        Settings settings = null;
        String mainValue = null;//mainValue
        String value2 = null;//value2
        if (null != settingsService.getSettingsByFk("NO_INTERESTRATE_TRANSLIMIT")) {
            settings = settingsService.getSettingsByFk("NO_INTERESTRATE_TRANSLIMIT");
            mainValue = settings.getMainValue();
            value2 = settings.getValue2();
            if (null != mainValue && null != value2) {
                Double minTransMoney = Double.parseDouble(mainValue);
                Double maxTransMoney = Double.parseDouble(value2);
                if (transMoney != 0 && transMoney < minTransMoney) {
                    limitMap.put("code", "fk0001");
                    limitMap.put("value", minTransMoney);
                    limitMap.put("description", "支付失败-金额超限，单笔支持最小金额为$param元!");
                    return limitMap;
                } else if (transMoney != 0 && transMoney > maxTransMoney) {
                    limitMap.put("code", "fk0002");
                    limitMap.put("value", maxTransMoney);
                    limitMap.put("description", "支付失败-金额超限，单笔支持最大金额为$param元!");
                    return limitMap;
                }
            }
        }
        return null;
    }

    /**
     * 计算手续费
     *
     * @param user
     * @param roleId
     * @param transMoney
     * @param feeRate
     * @return
     */
    private Double calculateFee(User user, Long roleId, Double transMoney, Double feeRate) {
        double fee = NumberUtil.roundF2(feeRate * transMoney);
        if (3 == roleId.intValue()) {//封顶版
            if (fee > user.getFdMaxFee()) {
                fee = user.getFdMaxFee();
            } else if (fee < user.getFdMinFee()) {
                fee = user.getFdMinFee();
            }
        } else if (4 == roleId.intValue()) {
            fee = 0.0;
        }
        return fee;
    }

    /**
     * 判定是否为复合卡（二磁道d后面YYMMa 第五位 a = 2 或 a = 6 证明是复合卡）
     *
     * @param track2Data
     * @return
     */
    private boolean isFhCard(String track2Data) {
        track2Data = track2Data.toLowerCase();
        String data = track2Data.split("d")[1];
        int fv = Integer.valueOf(data.substring(4, 5));
        if (fv == 2 || fv == 6) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 零利率收款
     * @return
     * @throws Exception
     */
    public String zeroFLReceivablesToCard() throws Exception {
        log.debug("--- zeroFLReceivablesToCard() start ---");
        JSONObject js = JSONObject.fromObject(getRequest().getAttribute(FC_DATA));
        terminalTypeId = Long.parseLong(js.getString("terminalTypeId"));
        if (js.containsKey("userId"))
            userId = Long.parseLong(js.getString("userId"));
        if (js.containsKey("transAmt"))
            transAmt = js.getString("transAmt");
        if (js.containsKey("accountNumber"))
            accountNumber = js.getString("accountNumber");
        roleId = Long.parseLong(getJsonString("roleId"));

        //查询用户
        User user = userService.getUserById(userId);
        if (!user.getRoleId().equals(roleId) && user.getRoleId() != 1L) {
            log.error("前台传入roleId = " + roleId + " 与当前用户注册roleId = " + user.getRoleId() + "不相符!");
            Map<String, Object> resMap = new HashMap<String, Object>();
            resMap.put("reqCode", "0001");
            resMap.put("reqMsg", "收款交易时,roleId参数异常!");
            sendAppMsg(resMap);
            return null;
        }

        //限额判断
        Map<String, Object> map = noInterestRateLimit(Double.parseDouble(transAmt) / 100);
        if (map != null) {
            sendAppErrorMsg(map.get("code").toString(), map.get("value").toString());
            return null;
        }


        //屏蔽伪卡
        if (transRefuseCardService.isRefuseCard(accountNumber)) {
            sendAppErrorMsg("6073", accountNumber);
            return null;
        }

        //支付  接口
        ZeroFLPayOrder(user, userId);
        return null;
    }

    /**
     * 秒到收款
     * @return
     * @throws Exception
     */
    public String secondsReceivablesToCard() throws Exception {
        log.debug("--- secondsReceivablesToCard() start ---");
        JSONObject js = JSONObject.fromObject(getRequest().getAttribute(FC_DATA));
        terminalTypeId = Long.parseLong(js.getString("terminalTypeId"));
        if (js.containsKey("userId"))
            userId = Long.parseLong(js.getString("userId"));
        if (js.containsKey("transAmt"))
            transAmt = js.getString("transAmt");
        if (js.containsKey("accountNumber"))
            accountNumber = js.getString("accountNumber");
        roleId = Long.parseLong(getJsonString("roleId"));
        //查询用户
        User user = userService.getUserById(userId);
        if (!user.getRoleId().equals(roleId) && user.getRoleId() != 1L) {//这块添加过滤零费率支付
            log.error("前台传入roleId = " + roleId + " 与当前用户注册roleId = " + user.getRoleId() + "不相符!");
            Map<String, Object> resMap = new HashMap<String, Object>();
            resMap.put("reqCode", "0001");
            resMap.put("reqMsg", "收款交易时,roleId参数异常!");
            sendAppMsg(resMap);
            return null;
        }
        //在数据库中获取 单日单用户交易金额限制
        double ssTranslimit = getConfig("SECONDSTO_TRANS_LIMIT");
        double money = Double.parseDouble(transAmt) / 100;
        Map<String, Object> ssMap = userTransLimitService.ssTransLimit(userId, roleId, money, 1L, ssTranslimit);
        if (ssMap != null) {
            sendAppErrorMsg(ssMap.get("code").toString(), ssMap.get("value").toString());
            return null;
        }

        //屏蔽伪卡
        if (transRefuseCardService.isRefuseCard(accountNumber)) {
            sendAppErrorMsg("6073", accountNumber);
            return null;
        }

        //支付  接口
        SecondsTOPayOrder(user, roleId);
        return null;
    }

    /**
     * 秒到收款
     *
     * @return
     * @throws Exception
     */
    public String SecondsTOPayOrder(User user, long roleId) throws Exception {
        functionKey = "SECONDSTO";
        Qian4SendLog send = null;//发送数据
        TransPriorSettle transPriorSettle = null;
        TransOrder transOrder = null;
        Map<String, Object> result = null;
        try {
            if (!checkPIV(functionKey)) {
                log.warn("秒到收款时,银行接口暂停使用!");
                return null;
            }
            user = userService.getUserById(userId);

            if (null != user) {
                User user1 = new User();
                user1.setId(userId);
                user1.setDeleted(0);
                user = userService.searchEntity(user1);
                if (user == null) {
                    Map<String, Object> resMap = new HashMap<String, Object>();
                    log.warn("秒到收款时, 用户Id=" + userId + " 对应的用户不存在!");
                    resMap.put("reqCode", "6004");
                    resMap.put("reqMsg", "用户：" + userId + " 该用户被销户或暂停使用！");
                    resMap.put("channelId", "");
                    sendAppMsg(resMap);
                    return null;
                }
                //获取user对应的刷卡器类型
                Integer machineType = user.getMachineType();
                Object[] resultA = secondsTOAssembleBean(user);
                if (null == resultA) return null;

                send = (Qian4SendLog) resultA[0];
                transOrder = (TransOrder) resultA[1];

                if (!checkCard(send.getAccountNumber(), userId)) {
                    log.warn("秒到收款时,该卡在绑定卡表中不存在");
                    Map<String, Object> resMap = new HashMap<String, Object>();
                    resMap.put("reqCode", "6004");
                    resMap.put("reqMsg", "秒到收款时,该卡未被绑定");
                    sendAppMsg(resMap);
                    return null;
                }
                //添加刷卡器类型
                transOrder.setMachineType(machineType);
                int channelId = user.getChannelId().intValue();
                //添加判断:通道是否支持复合卡刷磁条, 是否需要跳转到其他通道
                channelId = whetherChangeChannel(String.valueOf(channelId), send);

                Tchannel tc = tchannelService.searchMobileTchannelByCode(channelId);
                send.setCollectionType(tc.getCode());
                send.setRoleId(roleId);
                //秒到业务单独计算手续费率
                double ssFeeTate = getConfig("SECONDSTO_FEERATE");
                transOrder.setFeeRate(ssFeeTate);
                double fee = calculateFee(user, transOrder.getRoleId(), transOrder.getTransMoney(), transOrder.getFeeRate());

                transOrder.setFeeMoney(fee);
                transOrder.setChargeAmount(transOrder.getTransMoney() - fee);
                //获取数据库中e点的交易限额
                UserTransLimit limit = new UserTransLimit();
                limit.setFunctionKey("EPOINTTRANSLIMIT");
                limit = (UserTransLimit) userTransLimitService.searchEntity(limit);
                long dayCnt = limit.getDayCnt();//得到e点的限额

                switch (channelId) {
                    case PurchaseBaseAction.TC_EPOINT:
                        if (dayCnt > transOrder.getTransMoney()) {
                            send = ds_ECBService.initSend(send, tc);
                            send.setCollectionType(PurchaseBaseAction.TC_ECB);
                        } else {
                            send = ds_ideaioeService.initSend(send, tc);
                        }
                        break;
                    case PurchaseBaseAction.TC_ECB:
                        send = ds_ECBService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_RuiSheng:
                        send = ds_RuiShengService.initSend(send, tc);
                        if (send.getBatchId() == null) {
                            tc = tchannelService.searchMobileTchannelByCode(PurchaseBaseAction.TC_ECB);
                            send = ds_ECBService.initSend(send, tc);
                            send.setCollectionType(PurchaseBaseAction.TC_ECB);
                        }
                        break;
                    case PurchaseBaseAction.TC_RuiSheng_GT:
                        send = ds_RuiShengGTService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGYI:
                        send = ds_zytlPayService.initSend(send);
                        break;
                    case PurchaseBaseAction.TC_POSP:
                        send = ds_pospService.initSend(send, tc, user.getId());
                        break;
                    case PurchaseBaseAction.TC_Uinpay:
                        send = ds_uinpayPayService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_YinShengBao:
                        send = ds_yinShengBaoService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_POS:
                        send = ds_posService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHIFUTONG:
                        send = ds_zhifutongService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_HANXIN:
                        send = ds_HanXinService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGLAN:
                        send = ds_zhongLanService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_KAYINKA:
                        send = ds_kaYinKaService.initSend(send, tc);
                        break;
                }

                //下订单
                transPriorSettle = accountManageQ4Service.advanceOrder(transOrder, send, send.getCollectionType());

                //提交给 Q48 接口
                PurchaseResult rs = null;
                switch (send.getCollectionType()) {
                    case PurchaseBaseAction.TC_ECB:
                        rs = ds_ECBService.billPayment(send, tc);
                        break;//ECB
                    case PurchaseBaseAction.TC_RuiSheng:
                        rs = ds_RuiShengService.billPayment(send, tc);
                        break;//瑞晟
                    case PurchaseBaseAction.TC_RuiSheng_GT:
                        rs = ds_RuiShengGTService.billPayment(send, tc);
                        break;//瑞晟
                    case PurchaseBaseAction.TC_ZHONGYI:
                        long amtLimit = Long.valueOf(ConConfig.getAttribute("ZYTL_FDORFL_AMT_LIMIT"));
                        long transMoney = Long.valueOf(send.getTransAmt());
                        if (transMoney > amtLimit) {
                            send.setRoleId(3l);
                        } else {
                            send.setRoleId(2l);
                        }
                        rs = ds_zytlPayService.purchase(send, transOrder.getSignaturePath());
                        break;//ZYTL
                    case PurchaseBaseAction.TC_POSP:
                        rs = ds_pospService.billPayment(send, tc);//pos
                        break;
                    case PurchaseBaseAction.TC_EPOINT:
                        rs = ds_ideaioeService.billPayment(send, tc);//E点
                        break;
                    case PurchaseBaseAction.TC_Uinpay:
                        rs = ds_uinpayPayService.billPayment(send, tc);//优银
                        break;
                    case PurchaseBaseAction.TC_YinShengBao:
                        rs = ds_yinShengBaoService.billPayment(send, tc);//银生宝
                        break;
                    case PurchaseBaseAction.TC_POS:
                        rs = ds_posService.billPayment(send, tc);//大POS
                        break;
                    case PurchaseBaseAction.TC_ZHIFUTONG:
                        rs = ds_zhifutongService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_HANXIN:
                        rs = ds_HanXinService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGLAN:
                        rs = ds_zhongLanService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_KAYINKA:
                        rs = ds_kaYinKaService.billPayment(send, tc);
                        break;
                }

                //解析结果
                result = purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);
                log.debug(result);
                sendAppMsg(result);
                //自动生成提现订单且成功的交易
                if (1 == rs.getStatus() && "0000".equals(rs.getReqCode())){
                    settileSecCashMoney(transOrder);
                }
            } else {
                log.warn("收款交易时, 用户Id=" + userId + " 对应的用户不存在!");
                sendAppErrorMsg("6012", userId + "");
            }
        } catch (Exception e) {
            e.printStackTrace();
            revocationOrderTimeOut(send, transPriorSettle);
            throw e;
        } finally {
            send = null;
            transPriorSettle = null;
            transOrder = null;
            result = null;
        }
        return null;
    }

    public String ZeroFLPayOrder(User user, long roleId) throws Exception {
        functionKey = "ZEROFLPAY";
        Qian4SendLog send = null;//发送数据
        TransPriorSettle transPriorSettle = null;
        TransOrder transOrder = null;
        Map<String, Object> result = null;
        try {
            if (!checkPIV(functionKey)) {
                log.warn("零费率收款时, 银行接口暂停使用！");
                return null;
            }
            user = userService.getUserById(userId);

            if (null != user) {
                User user1 = new User();
                user1.setId(userId);
                user1.setDeleted(0);
                user = userService.searchEntity(user1);
                if (user == null) {
                    Map<String, Object> resMap = new HashMap<String, Object>();
                    log.warn("零费率收款时, 用户Id=" + userId + " 对应的用户不存在!");
                    resMap.put("reqCode", "6004");
                    resMap.put("reqMsg", "用户：" + userId + " 该用户被销户或暂停使用！");
                    resMap.put("channelId", "");
                    sendAppMsg(resMap);
                    return null;
                }
                //获取user对应的刷卡器类型
                Integer machineType = user.getMachineType();
                Object[] resultA = zeroFLPayAssembleBean(user);
                if (null == resultA) return null;

                send = (Qian4SendLog) resultA[0];
                transOrder = (TransOrder) resultA[1];

                //添加刷卡器类型
                transOrder.setMachineType(machineType);
                int channelId = user.getChannelId().intValue();
                //添加判断:通道是否支持复合卡刷磁条, 是否需要跳转到其他通道
                channelId = whetherChangeChannel(String.valueOf(channelId), send);

                Tchannel tc = tchannelService.searchMobileTchannelByCode(channelId);
                send.setCollectionType(tc.getCode());
                send.setRoleId(roleId);
                double fee = calculateFee(user, transOrder.getRoleId(), transOrder.getTransMoney(), transOrder.getFeeRate());
                transOrder.setFeeMoney(fee);
                transOrder.setChargeAmount(transOrder.getTransMoney() - fee);
                //获取数据库中e点的交易限额
                UserTransLimit limit = new UserTransLimit();
                limit.setFunctionKey("EPOINTTRANSLIMIT");
                limit = (UserTransLimit) userTransLimitService.searchEntity(limit);
                long dayCnt = limit.getDayCnt();//得到e点的限额

                switch (channelId) {
                    case PurchaseBaseAction.TC_EPOINT:
                        if (dayCnt > transOrder.getTransMoney()) {
                            send = ds_ECBService.initSend(send, tc);
                            send.setCollectionType(PurchaseBaseAction.TC_ECB);
                        } else {
                            send = ds_ideaioeService.initSend(send, tc);
                        }
                        break;
                    case PurchaseBaseAction.TC_ECB:
                        send = ds_ECBService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_RuiSheng:
                        send = ds_RuiShengService.initSend(send, tc);
                        if (send.getBatchId() == null) {
                            tc = tchannelService.searchMobileTchannelByCode(PurchaseBaseAction.TC_ECB);
                            send = ds_ECBService.initSend(send, tc);
                            send.setCollectionType(PurchaseBaseAction.TC_ECB);
                        }
                        break;
                    case PurchaseBaseAction.TC_RuiSheng_GT:
                        send = ds_RuiShengGTService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGYI:
                        send = ds_zytlPayService.initSend(send);
                        break;
                    case PurchaseBaseAction.TC_POSP:
                        send = ds_pospService.initSend(send, tc, user.getId());
                        break;
                    case PurchaseBaseAction.TC_Uinpay:
                        send = ds_uinpayPayService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_YinShengBao:
                        send = ds_yinShengBaoService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_POS:
                        send = ds_posService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHIFUTONG:
                        send = ds_zhifutongService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_HANXIN:
                        send = ds_HanXinService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGLAN:
                        send = ds_zhongLanService.initSend(send, tc);
                        break;
                    case PurchaseBaseAction.TC_KAYINKA:
                        send = ds_kaYinKaService.initSend(send, tc);
                        break;
                }

                //下订单
                transPriorSettle = accountManageQ4Service.advanceOrder(transOrder, send, send.getCollectionType());

                //提交给 Q48 接口
                PurchaseResult rs = null;
                switch (send.getCollectionType()) {
                    case PurchaseBaseAction.TC_ECB:
                        rs = ds_ECBService.billPayment(send, tc);
                        break;//ECB
                    case PurchaseBaseAction.TC_RuiSheng:
                        rs = ds_RuiShengService.billPayment(send, tc);
                        break;//瑞晟
                    case PurchaseBaseAction.TC_RuiSheng_GT:
                        rs = ds_RuiShengGTService.billPayment(send, tc);
                        break;//瑞晟
                    case PurchaseBaseAction.TC_ZHONGYI:
                        long amtLimit = Long.valueOf(ConConfig.getAttribute("ZYTL_FDORFL_AMT_LIMIT"));
                        long transMoney = Long.valueOf(send.getTransAmt());
                        if (transMoney > amtLimit) {
                            send.setRoleId(3l);
                        } else {
                            send.setRoleId(2l);
                        }
                        rs = ds_zytlPayService.purchase(send, transOrder.getSignaturePath());
                        break;//ZYTL
                    case PurchaseBaseAction.TC_POSP:
                        rs = ds_pospService.billPayment(send, tc);//pos
                        break;
                    case PurchaseBaseAction.TC_EPOINT:
                        rs = ds_ideaioeService.billPayment(send, tc);//E点
                        break;
                    case PurchaseBaseAction.TC_Uinpay:
                        rs = ds_uinpayPayService.billPayment(send, tc);//优银
                        break;
                    case PurchaseBaseAction.TC_YinShengBao:
                        rs = ds_yinShengBaoService.billPayment(send, tc);//银生宝
                        break;
                    case PurchaseBaseAction.TC_POS:
                        rs = ds_posService.billPayment(send, tc);//大POS
                        break;
                    case PurchaseBaseAction.TC_ZHIFUTONG:
                        rs = ds_zhifutongService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_HANXIN:
                        rs = ds_HanXinService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_ZHONGLAN:
                        rs = ds_zhongLanService.billPayment(send, tc);
                        break;
                    case PurchaseBaseAction.TC_KAYINKA:
                        rs = ds_kaYinKaService.billPayment(send, tc);
                        break;
                }

                //解析结果
                result = purchaseResolveResult(send, rs, transOrder, transPriorSettle, user, tc);
                log.debug(result);
                sendAppMsg(result);
            } else {
                log.warn("收款交易时, 用户Id=" + userId + " 对应的用户不存在!");
                sendAppErrorMsg("6012", userId + "");
            }
        } catch (Exception e) {
            e.printStackTrace();
            revocationOrderTimeOut(send, transPriorSettle);
            throw e;
        } finally {
            send = null;
            transPriorSettle = null;
            transOrder = null;
            result = null;
        }
        return null;
    }
}
